package stdio.costa.imoca.card;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;

import stdio.costa.imoca.model.Address;
import stdio.costa.imoca.model.Image;
import stdio.costa.imoca.model.Postcard;
import stdio.costa.imoca.model.PostcardTemplate;
import stdio.costa.imoca.utils.AsposeUtils;
import stdio.costa.imoca.utils.ImageUtils;

import com.aspose.words.Document;
import com.aspose.words.DocumentBuilder;
import com.aspose.words.IReplacingCallback;
import com.aspose.words.SaveFormat;
import com.aspose.words.Shape;

/**
 * 最终产物是154*111的卡片，卡片最终规格是148*105，长宽各自减去3*2的印刷出血.
 * 由于生成使用模版，所以要求模版来控制长宽，此处不做长宽处理。
 * @author 张桂林
 */
public class PostcardPreviewBuilder extends AbstractPreviewBuilder implements PreviewBuilder {
	
	private static final Pattern WISH_PATTERN = Pattern.compile("\\$\\{wish\\}");
	
	private final Postcard postcard;
	
	public PostcardPreviewBuilder(Postcard postcard) {
		super();
		this.postcard = postcard;
	}
	
	@Override
	protected Image createBack() throws Exception {
		PostcardTemplate template = postcard.getTemplate();
		Document document = new Document(new ByteArrayInputStream(template.getBack().getData()));
		DocumentBuilder builder = new DocumentBuilder(document);
		attachReceiverAddress(document, postcard.getAddress());
		// FIXME
//		attachSenderAddress(document, postcard.getOwner().getAddress());
		attachSenderAddress(document, postcard.getAddress());
		attachWish(document, builder, postcard.getWish());
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		document.save(out, SaveFormat.PNG);
		byte[] back = attachPostmarks(out.toByteArray(), postcard.getPostmarks());
		return new Image(back, "image/png", postcard.getOwner());
	}
	

	private byte[] attachPostmarks(byte[] byteArray, List<Image> postmarks) throws IOException {
		if(postmarks != null && !postmarks.isEmpty()) {
			for(Image postmark : postmarks) {
				byteArray = ImageUtils.addWatermarkRandomly(byteArray, postmark.getData());
			}
		}
		return byteArray;
	}

	private void attachWish(Document document, DocumentBuilder builder, Image wish) throws Exception {
		IReplacingCallback callback = new MarkableImageReplacingCallback("${wish}", wish.getData(), builder);
		document.getRange().replace(WISH_PATTERN, callback, true);
		document.getRange().replace(WISH_PATTERN, callback, false);
	}

	private void attachReceiverAddress(Document document, Address address) throws Exception {
		AsposeUtils.replace(document, "${to}", address.getWhom());
		AsposeUtils.replace(document, "${province}", address.getProvince());
		AsposeUtils.replace(document, "${city}", address.getCity());
		AsposeUtils.replace(document, "${district}", address.getDistrict());
		AsposeUtils.replace(document, "${detail}", address.getDetail());
		attachPostcode(document, address.getPostcode(), "p");
	}
	
	private void attachPostcode(Document doc, String postcode, String key) throws Exception {
		char[] chars = postcode.toCharArray();
		for(int i = 0; i < chars.length; i++) {
			int n = i + 1;
			AsposeUtils.replace(doc, "${" + key + n + "}", String.valueOf(chars[i]));
		}
	}
	
	private void attachSenderAddress(Document document, Address address) throws Exception {
		AsposeUtils.replace(document, "${from}", address.getWhom());
		AsposeUtils.replace(document, "${fprovince}", address.getProvince());
		AsposeUtils.replace(document, "${fcity}", address.getCity());
		AsposeUtils.replace(document, "${fdistrict}", address.getDistrict());
		AsposeUtils.replace(document, "${fdetail}", address.getDetail());
		AsposeUtils.replace(document, "${fpostcode}", address.getPostcode());
	}
	
	@Override
	protected Image createFront() throws Exception {
		PostcardTemplate template = postcard.getTemplate();
		Document document = new Document(new ByteArrayInputStream(template.getFront().getData()));
		DocumentBuilder builder = new DocumentBuilder(document);
		Shape shape = builder.insertImage(postcard.getPhoto().getData());
		shape.setWidth(builder.getPageSetup().getPageWidth());
		shape.setHeight(builder.getPageSetup().getPageHeight());
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		document.save(out, SaveFormat.PNG);
		return new Image(out.toByteArray(), "image/png", postcard.getPhoto().getOwner());
	}
	
}
